home *** CD-ROM | disk | FTP | other *** search
- TITLE INTRIG - Triginometric routines in fixed point
-
- COMMENT $
-
- // All code and algorithms used are by Dave Stampe.
- // These are some of the fastest integer trig routines
- // in 32 bit fixed point around, and are accurate to 3 LSB
-
- // See INTMATH.H for formats
-
- /*
- This code is part of the VR-386 project, created by Dave Stampe.
- VR-386 is a desendent of REND386, created by Dave Stampe and
- Bernie Roehl. Almost all the code has been rewritten by Dave
- Stampre for VR-386.
-
- Copyright (c) 1994 by Dave Stampe:
- May be freely used to write software for release into the public domain
- or for educational use; all commercial endeavours MUST contact Dave Stampe
- (dstampe@psych.toronto.edu) for permission to incorporate any part of
- this software or source code into their products! Usually there is no
- charge for under 50-100 items for low-cost or shareware products, and terms
- are reasonable. Any royalties are used for development, so equipment is
- often acceptable payment.
-
- ATTRIBUTION: If you use any part of this source code or the libraries
- in your projects, you must give attribution to VR-386 and Dave Stampe,
- and any other authors in your documentation, source code, and at startup
- of your program. Let's keep the freeware ball rolling!
-
- DEVELOPMENT: VR-386 is a effort to develop the process started by
- REND386, improving programmer access by rewriting the code and supplying
- a standard API. If you write improvements, add new functions rather
- than rewriting current functions. This will make it possible to
- include you improved code in the next API release. YOU can help advance
- VR-386. Comments on the API are welcome.
-
- CONTACT: dstampe@psych.toronto.edu
- */
-
- $
-
- .MODEL large
-
- .CODE INTMATH
-
- ;include 3dstruct.inc
-
- .DATA
-
- extrn _sintable ; arrays of 258 dwords
- extrn _atantable ; <3.29> args -> <16.16> angle
-
-
- ; # define XFSC 536870912 /* 2**29 for shifting xform coeffs to long */
-
- .CODE INTMATH
-
- ; /*************** INTEGER SINE, COSINE **************/
-
- ;/* return(XFSC * sin(3.14159/180*angle/65536.0));*/
- ;long isine(long angle) /* returns <3.29> sine of <16.16> angle */
-
- angle equ [bp+8] ; arguments
-
- PUBLIC _isine
-
- _isine proc far
-
- .386
- push ebp
- mov ebp,esp
-
- push esi
- push edi
- push ecx
-
- mov eax,angle
- mov edx,5B05B05Bh
- imul edx
- shrd eax,edx,29 ;/* convert so 90 deg -> 256<<16 */
- adc eax,0 ;/* 2 upper bits = quadrant */
- mov angle,eax ;/* 16 lsb used to interp. */
-
- mov ebx,eax
- mov esi,eax
- mov edx,eax
-
- shr ebx,14 ;/* 8 bit 2.84*degree index */
- and ebx,03FCh
- test esi,01000000h
- jz forward
- not edx
- xor ebx,03FCh
- forward:
- les di,DWORD PTR _sintable
- mov ecx,DWORD PTR es:[bx+di]
- mov eax,DWORD PTR es:[bx+di+4] ;/* lookup this, next entry */
-
- sub eax,ecx
-
- and edx,0000FFFFh ;/* compute interp. factor */
- mul edx
- shrd eax,edx,16
- adc ecx,eax ;/* add in */
-
- test esi,02000000h
- jz positive
- neg ecx
- positive:
- mov eax,ecx ;return result in dx:ax
- shld edx,eax,16 ; dlete to rtn in eax
-
- pop ecx
- pop edi
- pop esi
-
- mov esp,ebp
- pop ebp
- ret
-
- _isine endp
-
-
- ; long icosine(long angle)
-
- angle equ [bp+8] ; arguments
-
- PUBLIC _icosine
-
- _icosine proc far
-
- .386
- push ebp
- mov ebp,esp
-
- mov eax,angle
- add eax,005A0000h ; just ask for sine(90+angle)
- push eax
- call far ptr _isine
- add esp,4
-
- mov esp,ebp
- pop ebp
- ret
-
- _icosine endp
-
-
- ;/************ INVERSE TRIG FUNCTIONS *************/
-
- ;long arcsine(long x) /* <3.29> args -> <16.16> angle */
- ;{ /* have to use table in reverse */
-
- x equ [bp+8] ; arguments
-
- sign equ [bp-2] ; locals
-
- PUBLIC _arcsine
-
- _arcsine proc far
-
- .386
- push ebp
- mov ebp,esp
- sub esp,14
-
- push esi
- push edi
- push ecx
-
- mov WORD PTR sign,0
-
- mov eax,x
- or eax,eax
- je ret_eax ; 0->0 mapping common
- jg posarg
-
- inc WORD PTR sign ; negative argument
- neg eax
- posarg:
- cmp eax,20000000h ; 1.0 or greater?
- jl notone
- mov eax,005A0000h ; 90<<16 returned
- jmp ret_signed
- notone:
- les bx,DWORD PTR _sintable ; begin binary search
-
- xor ecx,ecx
- cmp eax,es:[bx+512]
- jb b1
- add ebx,512
- or ecx,00800000h
- b1:
- cmp eax,es:[bx+256]
- jb b2
- add ebx,256
- or ecx,00400000h
- b2:
- cmp eax,es:[bx+128]
- jb b3
- add ebx,128
- or ecx,00200000h
- b3:
- cmp eax,es:[bx+64]
- jb b4
- add ebx,64
- or ecx,00100000h
- b4:
- cmp eax,es:[bx+32]
- jb b5
- add ebx,32
- or ecx,00080000h
- b5:
- cmp eax,es:[bx+16]
- jb b6
- add ebx,16
- or ecx,00040000h
- b6:
- cmp eax,es:[bx+8]
- jb b7
- add ebx,8
- or ecx,00020000h
- b7:
- cmp eax,es:[bx+4]
- jb b8
- add ebx,4
- or ecx,00010000h
- b8:
- sub eax,es:[bx] ; OK, got entry lower than x
- je nointerp ; compute difference
- mov esi,es:[bx+4] ; and interpolate
- sub esi,es:[bx]
- je okinterp
- cmp eax,esi
- jb okinterp
- add ecx,00010000h
- jmp nointerp
- okinterp:
- cdq
- shld edx,eax,16
- shl eax,16
- idiv esi
- mov cx,ax
- nointerp:
- mov eax,05A000000h ;/* convert to <16.16> angle */
- imul ecx
- mov eax,edx
- ret_signed: ; add sign to result
- test WORD PTR sign,-1
- je ret_eax
- neg eax
- ret_eax:
- shld edx,eax,16 ; eax -> dx:ax
-
- pop ecx
- pop edi
- pop esi
- mov esp,ebp
- pop ebp
- ret
-
- _arcsine endp
-
-
- ;long arccosine(long x)
-
- x equ [bp+8] ; arguments
-
- PUBLIC _arccosine
-
- _arccosine proc far
-
- .386
- push ebp
- mov ebp,esp
-
- push DWORD PTR x
- call far ptr _arcsine
- add esp,4
-
- not dx ; negate dx:ax
- not ax
- add ax,1
- adc dx,90 ; (90*65536L - arcsine(x));
-
- mov esp,ebp
- pop ebp
- ret
-
- _arccosine endp
-
-
- ; /********** INVERSE TANGENT **********/
-
- ;/* we can use a table for atan */
- ;/* as slope is fairly constant */
- ;long arctan2(long y, long x)
-
-
- y equ [bp+8] ; arguments
- x equ [bp+12]
-
- sx equ [bp-2] ; locals (quadrant flags)
- sy equ [bp-4]
- g45 equ [bp-6]
-
- PUBLIC _arctan2
-
- _arctan2 proc far
-
- .386
- push ebp
- mov ebp,esp
- sub esp,12
-
- push esi
- push edi
- push ecx
-
- mov WORD PTR sx,0
- mov WORD PTR sy,0
- mov WORD PTR g45,0
-
- mov eax,DWORD PTR x
- or eax,eax
- jge x_pos
- inc WORD PTR sx
- neg eax
- x_pos:
- mov edx,DWORD PTR y
- or edx,edx
- jge y_pos
- inc WORD PTR sy
- neg edx
- y_pos:
- or eax,eax
- jne nonzero_x
- mov eax,005A0000h ; 90<<16
- jmp sign_eax
- nonzero_x:
- or edx,edx
- jne nonzero_y
- mov eax,0 ; 0
- jmp sign_eax
- nonzero_y:
- cmp edx,eax
- jne not45deg
- mov eax,002D0000h ;/* 45 degrees */
- jmp sign_eax
- not45deg:
- jl not_ygtx
- inc WORD PTR g45 ; which quadrant?
- xchg eax,edx
- not_ygtx:
- mov ebx,eax ; save abs(x)
- xor eax,eax
- shrd eax,edx,8 ;/* shift so it will divide OK */
- shr edx,8
- idiv ebx ;/* y/x << 24 */
- mov ebx,eax
- shr ebx,14 ;/* top 8 bits are index into table */
- and ebx,03FCh
-
- les di, DWORD PTR _atantable
- mov ecx,DWORD PTR es:[bx+di]
- mov esi,DWORD PTR es:[bx+di+4]
-
- sub esi,ecx
- and eax,0000FFFFh ;/* bottom 16 bits interpolate */
- mul esi
- shr eax,16
- add eax,ecx
-
- test WORD PTR g45,-1
- je firstquad
- neg eax
- add eax,005A0000h ; result = 90*65536L - result;
- firstquad:
- sign_eax:
- test WORD PTR sx,-1 ; put result in proper quadrant
- je secquad
- sub eax,00B40000h
- test WORD PTR sy,-1
- jne out_eax
- neg eax
- jmp out_eax
- secquad:
- test WORD PTR sy,-1
- je out_eax
- neg eax
- out_eax:
- shld edx,eax,16 ; eax -> dx:ax
-
- pop ecx
- pop edi
- pop esi
-
- mov esp,ebp
- pop ebp
- ret
-
- _arctan2 endp
-
-
- end